home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / assembler / progasm1.lha / LEZIONI / LEZIONE2.TXT < prev    next >
Text File  |  1994-10-30  |  30KB  |  705 lines

  1.  
  2.  CORSO DI ASSEMBLER - LEZIONE 2
  3.  
  4. Avete capito esattamente come funziona il sorgente LEZIONE1a.s???
  5. Se non lo avete capito allora siete da neuro, e dovete smettere il corso.
  6.  
  7. Ora andiamo ad approfondire il linguaggio del 68000. Ho voluto anticipare
  8. col primo sorgente il fatto che il processore serve grossomodo per
  9. organizzare tutte le cose, ma che da solo non fa che cambiare valori
  10. nella sua memoria; mettendo certi valori in aree particolari di memoria
  11. come $dffxxx o $bfexxx si da corrente ai piedini dei chip della grafica,
  12. del suono e delle porte, e di conseguenza si puo', come nell'esempio
  13. precedente, cambiare il colore dello schermo, o leggendo queste locazioni
  14. sapere a che linea il pennello elettronico sia arrivato o se il bottone del
  15. mouse e' premuto. Per fare un gioco o una demo e' necessario usare un gran
  16. numero di questi indirizzi, detti REGISTRI, e quindi e' necessario conoscerli
  17. almeno quanto il linguaggio del 68000, (MOVE,JSR,ADD,SUB etc.) con cui si
  18. impostano.
  19. Per la programmazione di questo tipo come ho gia detto non si usano le LIBRERIE
  20. del ROM kickstart 1.2/1.3/2.0/3.0 (Ovvero le sue routines, o sottoprogrammi
  21. che consentono di aprire una finestra workbench o leggere un file, ad esempio)
  22. cioe' si usano pochissimo: ad esempio per evitare di far andare in guru il
  23. workbench o per disabilitare il multitasking.
  24. Ritengo necessario quindi in questa lezione n.2 di approfondire l'uso del
  25. 68000, una volta che si e' capito quale sia il suo ruolo.
  26.  
  27. La cosa piu' importante da imparare sono i modi di indirizzamento del
  28. processore, piu' che i comandi in se, infatti una volta imparato quello,
  29. ogni comando usa la stessa sintassi per l'indirizzamento e basta sapere
  30. che cosa fa il comando. Abbiamo gia detto che il processore opera sulla
  31. memoria che e' divisa in locazioni o indirizzi, la cui unita' di misura
  32. e' il byte, e solitamente l'indirizzo e' in formato esadecimale, cioe' in
  33. un formato numerico diverso da quello decimale, avendo infatti base 16.
  34. Questo non e' assolutamente un problema: mentre con i numeri decimali una
  35. sequenza di 30 numeri ad esempio fa: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 etc,
  36. in esadecimale fa 1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,10,11,12,13,14,15,16,17,18,
  37. 19,1a,1b,1c,1d,1e etc., cioe' nei numeri esadecimali si trovano anche le prime
  38. 6 lettere dell'alfabeto come se a fosse un 10, b un 11 eccetera; per convertire
  39. un numero da esadecimale a decimale o viceversa basta usare il comando "?"
  40. dell'asmone: per esempio facendo "?10000" si otterra' $2710, il corrispondente
  41. valore in esadecimale (i numeri esadecimali cominciano col $, quelli decimali
  42. non sono preceduti da niente e quelli binari da un %). I numeri esadecimali
  43. sono usati perche' sono piu' vicini al modo di pensare del computer che e'
  44. ovviamente BINARIO, cioe' composto di soli 0 ed 1.
  45. Come esempio per iniziare a capire i vari modi di indirizzamento del 68000
  46. useremo il comando CLR, che azzera la locazione di memoria indicata:
  47.  
  48.     CLR.B    $40000        ; vi ricordate la differenza tra .B, .W e .L?
  49.  
  50. Questa istruzione "pulira'", cioe' azzerera' il byte n. $40000, ossia
  51. l'indirizzo $40000. Questo e' il caso piu' semplice, detto ASSOLUTO; cioe'
  52. si indica direttamente in che indirizzo fare il CLR; nell'assemblatore sono
  53. in uso le LABEL, che servono ad identificare un punto del programma, in
  54. cui puo' esserci per esempio un byte da indicare: in questo caso invece di
  55. scrivere l'indirizzo si scrivera' il nome della LABEL; l'assemblatore allora
  56. scrivera' l'indirizzo effettivo del byte in questione: ad esempio, se
  57. modificassimo cosi' il nostro primo listato:
  58.  
  59. Waitmouse:
  60.     move.w    $dff006,$dff180    ; metti il valore di $dff106 in $dff180
  61.                 ; cioe' il VHPOSR nel COLOR0
  62.     btst    #6,$bfe001    ; tasto sinistro del mouse premuto?
  63.     bne.s    Waitmouse    ; se no ritorna a waitmouse e ripeti
  64.                 ; (il .s e' un equivalente del .b per questo
  65.                 ; tipo di comandi: bne.s = bne.b)
  66.     clr.b    dato1        ; AZZERA DATO1
  67.     rts            ; esci
  68.  
  69. dato1:
  70.     dc.b    $30    ; dc.b significa METTI IN MEMORIA IL SEGUENTE BYTE
  71.             ; in questo caso viene messo un $30 sotto dato1:
  72.  
  73. Prima di uscire con l'RTS si azzererebbe il byte contrassegnato con la label
  74. dato1:, che sarebbe allocato nella fase di assemblaggio (o compilazione)
  75. a qualche indirizzo assoluto ben preciso, ad esempio se il programma
  76. fosse assemblato dall'ASMONE a partire da $50000, si troverebbe in memoria
  77. dopo l'assemblaggio un CLR.B $5001c, cioe' l'indirizzo reale di dato1: ,
  78. non certo CLR.B DATO1, essendo dato1: un nome dato dal programmatore per
  79. contrassegnare il dc.b $30; di qui si intuisce anche l'utilita' delle label,
  80. infatti se si dovesse scrivere il listato indicando l'indirizzo numerico
  81. tutte le volte, nel caso che si aggiungesse una routine nel mezzo del
  82. programma si dovrebbero riscrivere tutti gli indirizzi. Per vedere a quale
  83. indirizzo vengono assemblate le label, basta usare il comando D dell'ASMONE:
  84. ad esempio dopo aver assemblato LEZIONE1a.s facendo "D waitmouse" otterrete il
  85. disassemblato della memoria a partire da waitmouse, e nel listato non
  86. appariranno le label, ma gli indirizzi reali.
  87.  
  88. Nei sorgenti esempio del corso noterete che non vengono mai indicati indirizzi
  89. numerici, ma solo LABEL, a parte gli indirizzi speciali come $dffxxx o $bfexxx.
  90. Nell'ultimo esempio ho usato un dc.b, che e' un comando dell'assemblatore che
  91. serve per inserire bytes definiti; per esempio per inserire un $12345678 in
  92. un dato punto del programma, dovro' usare il comando DC, e lo posso usare
  93. nelle 3 forme .B (BYTE), .W (WORD) e .L (LONGWORD):
  94.  
  95.     dc.b    $12,$34,$56,$78    ; in bytes
  96.  
  97.     dc.w    $1234,$5678    ; in words
  98.  
  99.     dc.l    $12345678    ; in longwords
  100.  
  101. Questo comando si usa anche per mettere delle frasi in memoria, ad esempio
  102. per mettere nel listato il testo che dovra' essere stampato a video da una
  103. routine di PRINT che stampi cio' che e' alla label TESTO:
  104.  
  105. TESTO:
  106.     dc.b    "tanti saluti"
  107.  
  108. oppure:
  109.     dc.b    'tanti saluti'
  110.  
  111. Di solito si termina il testo con uno zero:
  112.  
  113.     dc.b    "tanti saluti",0
  114.  
  115. Bisogna ricordarsi di mettere il testo tra virgolette e di usare il dc.b,
  116. non il dc.w o il dc.l!! I caratteri sono lunghi un byte ciascuno, e
  117. corrispondono ad un certo byte: ad esempio provate a fare ?"a" , e vedrete
  118. che corrisponde a $61, quindi scrivere dc.b "a" sara' equivalente a
  119. scrivere dc.b $61. Attenzione che le lettere grandi hanno valore diverso!
  120. un "A" per esempio e' $41. L'uso piu' comune del dc.b e' quello di definire
  121. byte, word, o zone piu' grandi dove verranno tenuti dei dati, ad esempio
  122. se si volesse fare un programma che registri il numero di volte che si preme
  123. un certo tasto, bisognera' definire una label seguita per esempio da un byte
  124. azzerato, ed ogni volta si aggiungera' 1 con il comando ADD a quella label,
  125. ossia a quel byte sotto la label, e all'uscita bastera' leggere il valore
  126. del byte:
  127.  
  128.     ; se il tasto e' premuto allora ADDQ.B #1,NUMPREMUTO, ossia
  129.     ; aggiungi uno al byte sotto la label numpremuto.
  130.  
  131. NUMPREMUTO:
  132.     dc.b    0
  133.  
  134. All'uscita del programma lo 0 iniziale sara' cambiato nel numero di volte
  135. che il tasto e' stato premuto. Un esempio simile e' in LEZIONE2a.s, che
  136. contiene anche un ampio commento. Vi consiglio di caricarlo in un altro
  137. buffer di testo: per selezionare uno dei 10 disponibili basta premere un
  138. tasto da F1 a F10, se per esempio avete LEZIONE2.TXT nel buffer di F1,
  139. premete F2, e caricateci LEZIONE2a.s con il comando "R". In seguito potete
  140. caricare LEZIONE2b.s e i seguenti nel buffer di F3,F4..., in modo da averli
  141. sempre a disposizione premendo un solo tasto; e' meglio comunque se seguite
  142. la LEZIONE.TXT, e man mano che trovate l'indicazione del sorgente esempio,
  143. continuate caricandolo in un altro buffer, eseguendolo e verificandolo,
  144. dopodiche' ritornate a leggere la LEZIONE da dove eravate: questo credo
  145. sia il miglior sistema per imparare, infatti si fa un po di teoria e si
  146. verifica subito.
  147.  
  148. Avete letto i commenti di LEZIONE2a.S?
  149.  
  150. Avrete visto l'importanza che hanno il byte, la word e la longword: per
  151. quanto riguarda il binario, per contare i bit, si comincia da destra e
  152. si va verso sinistra, al "contrario" insomma, e si parte da 0, non da 1, dunque
  153. un byte (che ha 8 bit) parte 0 e va fino al 7. Per esempio in questo numero:
  154.  
  155.   %000100010000
  156.  
  157. Sono "accesi" i bit 4 e 8. Per aiutarvi a numerarli potete fare cosi':
  158.  
  159.                 ;5432109876543210    - un utilizzo intelligente del ;
  160.       move.w   #%0011000000100100,$dffxxx
  161.  
  162. In questo caso sono "accesi" i bit 2,5,12 e 13 della WORD.
  163. Ricordo che un byte ha 8 bit, una word ne ha 16 (da 0 a 15), una longword ne
  164. ha 32 (da 0 a 31).
  165. Nell'istruzione
  166.  
  167.   BTST #6,$bfe001
  168.  
  169. Si controlla se il bit 6 del byte $bfe001 e' azzerato: se fosse:
  170.  
  171.    ;76543210
  172.    %01000000
  173.  
  174. Il bit 6 e' invece ad 1, dunque il mouse non e' premuto!!!
  175.  
  176. Per ricapitolare, un BYTE e' fatto di 8 bit: per indicarli, il primo a destra
  177. e' il bit 0, detto anche BIT MENO SIGNIFICATIVO. La numerazione procede da
  178. destra verso sinistra fino al 7, (ossia l'ottavo perche' si parte da 0 anziche'
  179. da 1: 01234567, ossia 8 bit); il bit 7 e' detto BIT PIU' SIGNIFICATIVO.
  180. E' piu' significativo perche' conta di piu' allo stesso modo in cui conta di
  181. piu', nel bigliettone da centomila, l'uno piu' a sinistra degli zeri piu' a
  182. destra.
  183. Un byte, al massimo puo' valere 255, ossia %11111111.
  184.  
  185. Una WORD invece e' fatto di 16 bit, ovvero due byte, allo stesso modo si parte
  186. da destra col bit 0, sempre il meno significativo, fino al bit 15 ultimo a
  187. sinistra, il piu' significativo. Al massimo puo' contenere 65535.
  188.  
  189. Una LongWord e' fatta di 32 bit, da 0 a 31, ossia 4 bytes, o 2 word, o se
  190. preferite una word e 2 bytes, insomma sempre 32 bit attaccati l'uno all'altro
  191. che al massimo possono contenere 4294967299 (4 miliardi!! come la lotteria!).
  192.  
  193. Ora procederemo con diversi modi di indirizzare: abbiamo visto che se
  194. facciamo ad esempio un CLR.W $100, azzereremo le locazioni $100 e $101,
  195. ossia una word a partire da $100 (essendo una word 2 bytes, e le locazioni
  196. divise in bytes, puliremo 2 bytes!!). Allo stesso modo un MOVE.B $100,$200
  197. copiera' il contenuto di $100 in $200. Questo si puo' indicare anche con
  198. le LABEL invece di specificare l'indirizzo, ad esempio MOVE.B LABEL1,LABEL2,
  199. ovvero copia il byte di LABEL1 in LABEL2. Ci sono pero' anche diversi modi
  200. di indirizzare, infatti posso fare un MOVE.L #$50000,LABEL2, ossia mettere
  201. un valore FISSO in LABEL2. Se ad esempio LABEL2 fosse all'indirizzo $60000,
  202. muoveremmo il valore $00050000 in $60000, ovvero i bytes facendo un M $60000:
  203. 00 05 00 00. Infatti quando c'e' il simbolo del cancelletto (#) prima di
  204. un numero o di una label significa che si sta muovendo un valore stabilito,
  205. e non il valore contenuto nell'indirizzo indicato con quel valore, come
  206. avviene se non ci sono cancelletti prima del numero o della LABEL. Per
  207. esempio analizziamo questi 2 casi:
  208.  
  209. 1)    MOVE.L    $50000,$60000    ; il valore contenuto negli indirizzi
  210.                 ; di memoria $50000,$50001,$50002,$50003
  211.                 ; vengono copiati in $60000,
  212.                 ; $60001,$60002,$60003, ossia una longword
  213.                 ; composta di 4 bytes viene copiata da un
  214.                 ; indirizzo all'altro.
  215.  
  216. 2)    MOVE.L    #$50000,$60000    ; Questa volta in $60000 viene messo il
  217.                 ; numero indicato dopo il cancelletto,
  218.                 ; ossia $50000. Da notare che questa
  219.                 ; volta l'indirizzo $50000 non viene letto
  220.                 ; e non c'entra assolutamente, viene
  221.                 ; implicato solo il $60000.
  222.  
  223. Se si usano delle label, non ci sono cambiamenti:
  224.  
  225. 1)    MOVE.L    CANE,GATTO    ; Il contenuto della longword cane, ossia
  226.                 ; $00123456 viene copiato nella longword
  227.                 ; GATTO (infatti $123456 e' la prima cosa
  228.                 ; sotto la label CANE)
  229.  
  230. prima dell'istruzione:
  231.  
  232. CANE:
  233.     dc.l    $123456
  234.  
  235. GATTO:
  236.     dc.l    0
  237.  
  238. dopo l'istruzione:
  239.  
  240. CANE:
  241.     dc.l    $123456
  242.  
  243. GATTO:
  244.     dc.l    $123456
  245.  
  246. 2)    MOVE.L    #CANE,GATTO    ; Questa volta l'INDIRIZZO della label
  247.                 ; CANE viene copiato nella label GATTO
  248.  
  249. prima dell'istruzione:    ; SUPPONIAMO CHE LA LABEL CANE: sia alla locazione
  250.             ; $34500, cioe' facendo un M CANE dopo aver assemblato
  251.             ; compare un :
  252.             ; 00034500 00 12 34 56 00 00 00 00 .....
  253.             ;          (cane)      (gatto)
  254.  
  255. CANE:
  256.     dc.l    $123456
  257.  
  258. GATTO:
  259.     dc.l    0
  260.  
  261. dopo l'istruzione:
  262.  
  263. CANE:
  264.     dc.l    $123456
  265.  
  266. GATTO:
  267.     dc.l    $34500    ; ossia DOVE E' LA LABEL CANE IN MEMORIA.
  268.  
  269. Da notare che se si faceva un MOVE.W #CANE,GATTO o un MOVE.B #CANE,GATTO
  270. l'assemblatore avrebbe dato un errore, in quanto un INDIRIZZO e' lungo
  271. una LONGWORD. In memoria un MOVE.L #LABEL,LABEL si trasforma in un istruzione
  272. del tipo MOVE.L #$12345,$12345, ossia l'assemblatore scrive l'indirizzo
  273. reale al posto delle label. Questo lo potete verificare con LEZIONE2b.s.
  274.  
  275. Ora affronteremo gli altri indirizzamenti con i registri (che sono piu'
  276. difficili); come avevo gia' accennato, ci sono 8 registri dati e 8 registri
  277. indirizzi: ossia D0,D1,D2,D3,D4,D5,D6,D7 sono i registri DATI, mentre
  278. a0,a1,a2,a3,a4,a5,a6,a7 sono i registri indirizzi. Premetto che il registro
  279. A7 e' detto anche SP o STACK POINTER, ed e' un registro particolare di cui
  280. parleremo dopo, quindi considerate di usare i registri indirizzi solo fino ad
  281. a6. questi indirizzi sono lunghi una longword ciascuno, ed sono in pratica
  282. una piccola memoria dentro il 68000, che di conseguenza e' molto veloce.
  283. Tramite i registri si possono fare varie cose, infatti esiste una sintassi
  284. particolare per i registri. Innanzitutto non si puo' lavorare per byte
  285. con i registri INDIRIZZI: per esempio un move.b LABEL,a0 da un messaggio
  286. di errore. Con i registri indirizzi a0,a1,etc si puo' dunque lavorare per
  287. longword o per word. Con i registri Dati D0,D1,etc, invece si possono usare
  288. sia .b che .w che .l. I registri indirizzi sono dedicati a contenere indirizzi,
  289. ed hanno comandi dedicati, come il LEA, che significa LOAD ENTIRE ADDRESS,
  290. ovvero carica l'indirizzo interamente nel registro (infatti questo comando non
  291. puo' essere lea.b, lea.w o lea.l, ma solo LEA essendo sempre .L)
  292. Per esempio, per mettere un valore nei registri indirizzi si possono usare
  293. 2 metodi:
  294.  
  295. 1)    MOVE.L    #$50000,A0    (oppure MOVE.L #LABEL,a0)
  296.  
  297. 2)    LEA    $50000,a0    (oppure LEA LABEL,A0)
  298.  
  299. Mentre il primo metodo si puo' usare sia con gli indirizzi che con i registri
  300. (es: move.l #$50000,d0 - move.l #$50000,LABEL - MOVE.L #$LABEL,LABEL...)
  301.  
  302. P.S: scrivere move.l #$50000,d0 o MOVE.L #$50000,D0 e' identico, si puo'
  303.      scrivere anche MoVe.L #$50000,d0, il risultato a livello di programma
  304.      e' identico, solo che esteticamente potete creare delle situazioni
  305.      simpatiche o orribili. Va fatto un discorso diverso per le LABEL: le
  306.      label possono essere identificate anche se in un punto del listato le
  307.      scrivete in minuscolo e in un'altro in maiuscolo, questo pero' solo
  308.      perche' e' settata nelle preferenze del TRASH'M-ONE questa opzione,
  309.      che e' UCase=UCase nel menu' "Assembler/Assemble..", che significa
  310.      "Upper Case=Lower Case, ossia lettere grandi=lettere piccole".
  311.      Se togliete questa opzione, nel riconoscimento delle label sara' tenuto
  312.      presente anche il maiuscolo/minuscolo, per cui Cane: sara' diverso da
  313.      CANE: o da cAne: o da caNe, eccetera eccetera.
  314.  
  315. il secondo metodo con il LEA si puo' usare solo con i registri indirizzi,
  316. di conseguenza si intuisce che questo modo e' piu' veloce: ricordatevi quindi
  317. che se volete mettere un indirizzo in un registro a0,a1... dovete usare il
  318. LEA seguito dall'indirizzo SENZA CANCELLETTO e dal registro in questione.
  319. Fate attenzione a questi 2 esempi:
  320.  
  321. 1)    MOVE.L    $50000,a0    ; metti in a0 il valore contenuto nella
  322.                 ; locazione $50000 (+$50001,$50002 e $50003
  323.                 ; in quanto 1 locazione e' lunga 1 byte, ed
  324.                 ; il move.l copia 4 bytes = 4 locazioni a
  325.                 ; partire in questo caso da $50000
  326.  
  327. 2)    LEA    $50000,a0    ; metti il numero $50000 in a0
  328.  
  329. State attenti quindi a maneggiare i MOVE con o senza il cancelletto ed i LEA,
  330. perche' e' facile nei primi tempi sbagliarsi e mettere l'indirizzo invece del
  331. valore di quell'indirizzo nel registro o viceversa. Come ulteriore commento
  332. di questa differenza consultate il programmino esempio LEZIONE2c.s
  333.  
  334. Con i registri indirizzi sono possibili vari tipi di indirizzamento:
  335. Per cominciare analizziamo queste 2 istruzioni:
  336.  
  337.     move.l    a0,d0    ; Metti il numero contenuto in a0 nel registro d0
  338.     move.l    (a0),d0 ; Metti la longword contenuta dall'indirizzo in a0
  339.             ; nel registro d0
  340.  
  341. L'indirizzamento tra parentesi si dice INDIRETTO, perche' anziche' venir
  342. copiato DIRETTAMENTE il valore in a0 viene copiato il valore contenuto
  343. nell'indirizzo che e' in a0. Un esempio pratico e' in LEZIONE2d.s
  344.  
  345. Usando l'indirizzamento indiretto si puo' agire sugli indirizzi INDIRETTAMENTE,
  346. ad esempio mettendo l'indirizzo del tasto del mouse e del colore 1 nei registri
  347. si puo' riscrivere il listato della lezione 1. Cosi' ho fatto in LEZIONE2e.s
  348.                           
  349.                          
  350. Facciamo gli ultimi esempi per togliere gli eventuali dubbi sull'indirizzamento
  351. indiretto:
  352.  
  353.     move.l a0,d0        ; copia il valore di A0 nel reg. d0
  354.     move.b (a0),d0        ; copia il byte contenuto nell'indirizzo
  355.                 ; in a0 nel reg. d0
  356.     move.w (a0),(a1)     ; copia la word contenuta dall'indirizzo
  357.                 ; in a0 all'indirizzo contenuto in a1
  358.                 ; (e seguente, essendo una word fatta di
  359.                 ; 2 bytes, ossia 2 indirizzi!)
  360.     clr.w    (a3)        ; pulisce (azzera) la word (2 bytes) "dentro"
  361.                 ; l'indirizzo in a3 - Piu' precisamente,
  362.                 ; viene azzerato il byte  dell'indirizzo in
  363.                 ; a3 e l'indirizzo seguente.
  364.     clr.l    (a3)        ; Come sopra, ma sono azzerati 4 indirizzi
  365.                 ; (una long = 4 bytes = 4 indirizzi)
  366.     move.l    d0,(a5)        ; viene copiato il valore di d0 nell'indirizzo
  367.                 ; contenuto in a5 ( piu' precisamente dovrei
  368.                 ; dire nell'indirizzo in a5, e nei 3 seguenti,
  369.                 ; in quanto una long occupa 4 indirizzi)
  370.     move.l    d0,a5        ; viene copiato il valore di d0 in a5
  371.  
  372. Mi raccomando! Toglietevi ogni dubbio sugli indirizzamenti fin qui studiati,
  373. consultando anche i sorgenti fino a LEZIONE2e.s, perche' gli indirizzamenti
  374. di cui parlero' ora si basano su quelli indiretti normali.
  375.  
  376. Vi comunico che questa e' la parte piu' astratta della lezione2, in quanto
  377. si devono imparare gli ultimi indirizzamenti del processore, ma vi assicuro
  378. che gia' dalla lezione 3 metterete in pratica il tutto e visualizzerete degli
  379. effetti video col copper!, quindi considerate che passata questa parte il resto
  380. del corso sara' tutto piu' PRATICO: a ogni spiegazione corrispondera' un nuovo
  381. effetto speciale o colore ultravivace, dunque fate lo sforzo di non annoiarvi
  382. e di non lasciar perdere ora, perche' io stesso lasciai perdere all'incirca
  383. a questo punto la prima volta che tentai di imparare a programmare in ASM,
  384. proprio perche' ero scoraggiato dal CASINO di comandi e parentesi aperte e
  385. chiuse che poi non riuscivo piu' a seguire. Vi assicuro pero' che una volta
  386. imparato a leggere i comandi, potete partire come una fucilata e imparare
  387. da voi leggendo listati qua' e la', facendo passi sempre piu' grandi: e'
  388. come imparare le regole di uno sport: uno che non conosce il set di
  389. istruzioni del 68000 e' come uno che non conosce le regole, ad esempio,
  390. del calcio: guardando le partite (i listati) costui non capira' nulla di
  391. cosa stanno facendo quegli scalmanati in un campo a dare calci ad una palla,
  392. e si annoiera' a morte, ma una volta capite le regole (indirizzamenti) potra'
  393. interpretare le fasi delle partite ed imparare sempre di piu' le tecniche
  394. di gioco (i trucchi della programmazione ed i registri della grafica).
  395.  
  396. Vediamo altri 2 modi di indirizzamento:
  397.                               
  398.     move.l    (a0)+,d0    ; Indiretto con post-incremento
  399.     move.l    -(a0),d0    ; Indiretto con pre-decremento
  400.  
  401. Analizziamo il primo indirizzamento ipotizzando questa situazione:
  402.  
  403.     lea    NONNO,a0    ; mettiamo in a0 l'indirizzo di NONNO:
  404.     MOVE.L    (a0)+,d0    ; mettiamo in d0 il valore .L contenuto
  405.                 ; dall'indirizzo in a0, ossia $3231020
  406.                 ; (come un normale MOVE.L (a0),d0)
  407.                 ; dopodiche' AGGIUNGIAMO 4 AL VALORE IN a0
  408.                 ; ovvero andiamo a PUNTARE alla long seguente
  409.                 ; con l'indirizzo in a0; se fosse stato un
  410.                 ; move.w (a0)+,d0 ad a0 DOPO (POST-INCREMENTO)
  411.                 ; sarebbe stato aggiunto 2 (una word=2),
  412.                 ; mentre nel caso di un MOVE.B (a0)+,d0
  413.                 ; sarebbe stato aggiunto 1, (un byte),
  414.                 ; ovvero sarebbe andato a puntare l'indirizzo
  415.                 ; seguente.
  416.     MOVE.L    (a0)+,d1    ; stessa cosa: copia in d1 il valore .L
  417.                 ; contenuto nell'indirizzo in a0, che ora
  418.                 ; contiene l'indirizzo di NONNO+una longword,
  419.                 ; ovvero NONNO+4, ossia $13478.
  420.     rts            ; ESCE!
  421.  
  422. NONNO:
  423.     dc.l    $3231020,$13478
  424.  
  425.     END
  426.  
  427. Possiamo tradurre questo tipo di indirizzamento con un 2 istruzioni:
  428.  
  429. 1)    MOVE.L    (a0)+,LABEL
  430.  
  431. E' equivalente a:
  432.  
  433. 1b)    MOVE.L    (A0),LABEL    ; copia una long dall'indirizzo in a0
  434.                 ; nella label
  435.     ADDQ.W    #4,a0        ; Aggiungi 4 ad a0 (.L=4)
  436.                 ; NOTA: se si addiziona un numero minore di
  437.                 ; 9 si usa il comando ADDQ invece di ADD
  438.                 ; perche' e' dedicato a tali numeri e veloce.
  439.                 ; Inoltre su registri INDIRIZZI se il numero
  440.                 ; che aggiungiamo o sottraiamo e' minore di
  441.                 ; $FFFF, ossia una word, si puo' usare il .W
  442.                 ; anziche' il .L, e si agira' comunque su
  443.                 ; tutta la longword dell'indirizzo.
  444. Allo stesso modo:
  445.  
  446. 2)    MOVE.W    (a0)+,LABEL
  447.  
  448. E' equivalente a:
  449.  
  450. 2b)    MOVE.W    (A0),LABEL    ; copia una word dall'indirizzo in a0
  451.                 ; nella label
  452.     ADDQ.W    #2,a0        ; Aggiungi 2 ad a0 (.W=2)
  453.  
  454. Allo stesso modo:
  455.  
  456. 3)    MOVE.B    (a0)+,LABEL
  457.  
  458. E' equivalente a:
  459.  
  460. 3b)    MOVE.B    (A0),LABEL    ; copia il byte contenuto nell'indirizzo
  461.                 ; in a0 nella label
  462.     ADDQ.W    #1,a0        ; Aggiungi 1 ad a0 (.B=1)
  463.  
  464. Dunque, riassumendo in altri termini, l'indirizzamento indiretto con post
  465. incremento si puo' paragonare ad un operaio di una catena di montaggio
  466. che PRIMA esegue il suo MOVE o la sua istruzione sul pezzo che sta sul nastro
  467. trasportatore, e ogni volta che ha fatto il suo lavoro sul pezzo sposta
  468. AVANTI il nastro trasportatore(l'indirizzo in a0) con un pedale (il +).
  469. Un esempio di loop puo' risultare piu' chiaro:
  470.  
  471. Inizio:
  472.     lea    $60000,a0    ; inizio pulizia
  473.     lea    $62000,a1    ; fine pulizia
  474. CLELOOP:
  475.     clr.l    (a0)+    ; azzera una long dall'indirizzo in A0 e aumenta a0
  476.             ; di una long, ossia di 4 indirizzi, in altre
  477.             ; parole pulisci una long e vai alla prossima
  478.     cmp.l    a0,a1    ; A0 e' arrivato a $62000? Ossia, a0 e' uguale ad a1?
  479.     bne.s    CLELOOP ; se non ancora, continua con un altro ciclo CLELOOP
  480.     rts
  481.  
  482. Come si vede, questo programmino pulisce la memoria dall'indirizzo $60000 a
  483. $62000, utilizzando un clr (a0)+ ripetuto fino a che non si e' arrivati
  484. all'indirizzo desiderato. Un esempio simile lo potete trovare in Lezione2f.s
  485.  
  486. Ora impareremo l'indirizzamento indiretto con pre-decremento, ossia un
  487. indirizzamento opposto a quello appena descritto, infatti invece di aumentare
  488. l'indirizzo contenuto rel registro dopo aver eseguito l'operazione, con
  489. un clr.l -(a0), per esempio, prima viene decrementato a0, poi viene eseguita
  490. l'istruzione sul nuovo indirizzo (in questo caso a0-4). Esempio:
  491.  
  492.     lea    NONNO,a0    ; mettiamo in a0 l'indirizzo di NONNO:
  493.     MOVE.L    -(a0),d0    ; a0 viene decrementato, in questo caso
  494.     rts            ; essendo un istruzione .L viene decrementato
  495.                 ; di 4, dopodiche' viene copiato in d0
  496.                 ; il valore .L contenuto dall'indirizzo
  497.                 ; in a0, ossia $12345678, cioe' NONNO-4
  498.                 ; (nel registro rimane il valore iniziale-4)
  499.     dc.l    $12345678    ; se fosse stato un
  500. NONNO:                ; move.w -(a0),d0 ad a0 PRIMA (PRE-INCREMENTO)
  501.     dc.l    $ffff0f0f    ; sarebbe stato sottratto 2 (una word=2),
  502.                 ; mentre nel caso di un MOVE.B -(a0),d0
  503.     END            ; sarebbe stato sottratto 1, (un byte),
  504.                 ; ovvero sarebbe andato a puntare l'indirizzo
  505.                 ; precedente.
  506.  
  507. Possiamo tradurre questo tipo di indirizzamento con un 2 istruzioni:
  508.  
  509. 1)    MOVE.L    -(a0),LABEL
  510.  
  511. E' equivalente a:
  512.  
  513. 1b)    SUBQ.W    #4,a0        ; Sottrai 4 ad a0 (.L=4)
  514.                 ; NOTA: se si sottrae un numero minore di
  515.                 ; 9 si usa il comando SUBQ invece di SUB
  516.                 ; perche' e' dedicato a tali numeri e veloce.
  517.  
  518.     MOVE.L    (A0),LABEL    ; copia una long dall'indirizzo in a0
  519.                 ; nella label
  520. Allo stesso modo:
  521.  
  522. 2)    MOVE.W    -(a0),LABEL
  523.  
  524. E' equivalente a:
  525.  
  526. 2b)    SUBQ.W    #2,a0        ; Sottrai 2 ad a0 (.W=2)
  527.     MOVE.W    (A0),LABEL    ; copia una word dall'indirizzo in a0
  528.                 ; nella label
  529.  
  530. Allo stesso modo:
  531.  
  532. 3)    MOVE.B    -(a0),LABEL
  533.  
  534. E' equivalente a:
  535.  
  536. 3b)    SUBQ.W    #1,a0        ; sottrai 1 ad a0 (.B=1)
  537.     MOVE.B    (A0),LABEL    ; copia il byte contenuto nell'indirizzo
  538.                 ; in a0 nella label
  539.  
  540. Riassumendo con l'operaio come prima, l'indirizzamento indiretto con pre
  541. decremento si puo' paragonare sempre ad un operaio di una catena di montaggio
  542. che PRIMA sposta INDIETRO il nastro trasportatore(l'indirizzo in a0) con un
  543. pedale (il -), POI esegue il suo MOVE o la sua istruzione sul pezzo che sta
  544. sul nastro trasportatore. Un esempio di loop:
  545.  
  546. Inizio:
  547.     lea    $62000,a0    ; inizio pulizia
  548.     lea    $60000,a1    ; fine pulizia
  549. CLELOOP:
  550.     clr.l    -(a0)    ; diminuisci a0 di una long e azzera quella long
  551.             ; in altre parole vai alla precedente long e puliscila
  552.     cmp.l    a0,a1    ; A0 e' arrivato a $60000? Ossia, a0 e' uguale ad a1?
  553.     bne.s    CLELOOP ; se non ancora, continua con un altro ciclo CLELOOP
  554.     rts
  555.  
  556. Come si vede, questo programmino pulisce la memoria dall'indirizzo $62000 a
  557. $60000, utilizzando un clr -(a0) ripetuto fino a che non si e' arrivati
  558. all'indirizzo desiderato (All'indietro pero'! mentre con (a0)+ si parte da
  559. $60000 e di 4 in 4 si arriva a $62000, in questo caso si parte da $62000
  560. e si arriva a $60000 indietreggiando di 4 in 4).
  561. Vedete Lezione2g.s e Lezione2h.s per verificare gli ultimi 2 indirizzamenti.
  562.  
  563. Ora impareremo come usare la distanza di indirizzamento:
  564. un MOVE.L $100(a0),d0 copia in d0 la long contenuta dall'indirizzo in a0+$100,
  565. ossia: se per esempio in A0 avevamo l'indirizzo $60200, in d0 ci andra' la
  566. longword contenuta dall'indirizzo $60300.
  567. Allo stesso modo un MOVE.L -$100(a0),d0 copiera' in d0 la long a partire
  568. dall'indirizzo $60100. Da notare che a0 non cambia di valore: semplicemente
  569. il processore calcola ogni volta a che indirizzo operare, facendo la somma
  570. tra il valore prima della parentesi e l'indirizzo nel registro tra parentesi.
  571. La massima distanza di indirizzamento e' da -32768 a 32767 (-$7FFF, $8000)
  572. Un esempio su questo tipo di indirizzamento e' Lezione2i.s
  573.  
  574. L'ultimo tipo di indirizzamento e' questo:
  575.  
  576.     MOVE.L    50(a0,d0),label
  577.  
  578. che ha sia una DISTANZA DI INDIRIZZAMENTO (il 50) che un INDICE (il d0):
  579. la distanza di indirizzamento e il contenuto di d0 sono tutti sommati per
  580. definire l'indirizzo da cui copiare il contenuto. In pratica e' come la
  581. distanza di indirizzamento, ma in piu' viene aggiunto anche il contenuto
  582. dell'altro registro alla distanza di indirizzamento, che in questo caso
  583. pero' va da un minimo di -128 ad un massimo di +128.
  584. non vi voglio annoiare con altri esempi su questo indirizzamento, potrete
  585. verificarlo quando lo troverete nei prossimi listati.
  586.  
  587. Per terminare la LEZIONE2, che se avete seguito bene vi rende in grado di
  588. seguire le operazioni di un qualsiasi programma in ASM, e' indispensabile
  589. spiegare il ciclo DBRA, che e' usato moltissimo: usando un registro dati
  590. si possono far eseguire delle istruzioni varie volte, basta mettere nel
  591. registro dati (sia esso d0,d1...) il numero di volte-1.
  592. Ad esempio la routine che pulisce la memoria fatta con il CLR.l (a0)+ puo'
  593. essere modificata con un loop DBRA che faccia eseguire la pulizia il
  594. numero desiderato di volte:
  595.  
  596. Inizio:
  597.     lea    $60000,a0    ; Inizio
  598.     move.l    #($2000/4)-1,d0    ; Metti in d0 il numero di cicli necessari
  599.                 ; per cancellare $2000 bytes: cioe'
  600.                 ; $2000/4 (ovvero DIVISO 4, perche' ogni
  601.                 ; clr.l pulisce 4 bytes), il tutto -1,
  602.                 ; perche' il loop viene eseguito una volta
  603.                 ; in piu'.
  604. CLEARLOOP:
  605.     CLR.L    (a0)+
  606.     DBRA    d0,CLEARLOOP
  607.     rts
  608.  
  609. Questa routine pulisce da $60000 a $62000 come l'esempio precedente in cui
  610. con il comando CMP si COMPARA a0 con a1, ossia si verifica se siamo arrivati
  611. a $62000 che e' in a1. In questo caso invece viene eseguito il CLR 2047 volte,
  612. provate infatti a fare ?($2000/4)-1 da ASMONE. Il DBRA funziona in questo modo:
  613. se per esempio la prima volta in d0 viene messo 2047, viene eseguito il CLR,
  614. poi arrivati al DBRA d0 viene diminuito di 1 e il processore salta nuovamente
  615. al CLR, lo esegue eccetera, fino a che d0 e' esaurito. Bisogna mettere il
  616. numero di cicli necessari meno uno perche' la prima volta il ciclo viene
  617. eseguito senza decrementare d0.
  618.  
  619. Come ultimo esempio studiatevi Lezione2l.s, che ha delle subroutines richiamate
  620. con il BSR e il ciclo DBRA in azione, utile per capire la struttura di un
  621. programma complesso.
  622.  
  623. Per terminare vorrei farvi notare la differenza tra un BSR ed un BEQ/BNE:
  624. nel caso del BSR label, il processore salta ad eseguire la routine sotto la
  625. label, fino a che non trova l'RTS, che lo fa tornare ad eseguire l'istruzione
  626. sotto il BSR label, dunque si puo' dire che ha eseguito una SOTTOROUTINE, cioe'
  627. una routine eseguita in mezzo ad un'altra routine:
  628.  
  629. principale:
  630.     move.l    roba1,d0
  631.  
  632.     move.l    roba2,d1
  633.  
  634.     bsr.s    sottoposto
  635.  
  636.     move.l    roba3,d2
  637.  
  638.     move.l    roba4,d3
  639.  
  640.     rts    ; FINE DELLA ROUTINE PRINCIPALE, TORNA ALL'ASMONE
  641.  
  642.  
  643. sottoposto:
  644.     move.l    robaccia,d4
  645.  
  646.     move.l    robaccia2,d5
  647.  
  648.     rts    ; FINE DELLA SOTTOROUTINE, TORNA A  "move.l roba3,d0", ossia
  649.         ; sotto il bsr.s sottoposto
  650.  
  651.  
  652. Nel caso di una DIRAMAZIONE beq/bne invece si prende O una strada O l'altra:
  653.  
  654.  
  655. principale:
  656.     move.l    roba1,d0
  657.  
  658.     move.l    roba2,a0
  659.  
  660.     cmp.b    d0,a0
  661.     bne.s    strada2
  662.  
  663.     move.l    roba3,d1
  664.  
  665.     cmp.b    d1,a0
  666.     beq.s    strada3
  667.  
  668.     move.l    roba4,d0
  669.  
  670.     rts    ; FINE DELLA ROUTINE PRINCIPALE, TORNA ALL'ASMONE
  671.  
  672.  
  673. strada2:
  674.     move.l    robaccia,d5
  675.  
  676.     move.l    robaccia2,d6
  677.  
  678.     rts    ; FINE ROUTINE, TORNA ALL'ASMONE, non sotto il bne!!!
  679.         ; qua abbiamo scelto questa strada, e come si trova un RTS
  680.         ; si torna all'ASMONE!!!
  681.  
  682.  
  683. strada3:
  684.     move.l    robaccia3,d1
  685.  
  686.     move.l    robaccia4,d2
  687.  
  688.     rts    ; FINE ROUTINE, TORNA ALL'ASMONE, non sotto il beq!!!
  689.         ; qua abbiamo scelto questa strada, e come si trova un RTS
  690.         ; si torna all'ASMONE!!!
  691.  
  692. Lo stesso vale per il BRA label, che significa SALTA A label, equivalente
  693. del JMP, per cui e' come un treno che trova uno scambio ai binari, non torna
  694. allo scambio quando ha finito il binario!! Arriva alla fine del binario e
  695. basta, senza teletrasporti alla star trek all'indietro.
  696.  
  697. Per un'ultima precisazione sui registri indirizzi, vedetevi Lezione2m.s
  698.  
  699. Per caricare la LEZIONE3.TXT potete fare in due modi: o scrivete "R" e
  700. andate a capo, facendo aprire il requester dove potete selezionare col mouse
  701. quale testo caricare (in questo caso df0:SORGENTI/LEZIONE3.TXT), oppure
  702. dovete assicurarvi di trovarvi nella directory giusta con un "V df0:LEZIONI"
  703. e potete caricarla in seguito con un semplice "R LEZIONE3.TXT"
  704.  
  705.